/*******************************************************************************
 * This file is part of blueprint4j www.blueprint4j.org.
 * 
 *     blueprint4j is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Lesser General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 * 
 *     blueprint4j is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Lesser General Public License for more details.
 * 
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with blueprint4j. If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package blueprint4j.db;

import blueprint4j.utils.*;

import java.util.Vector;
/**
 * Entity Children are declared the entity class Logic can now be applied to
 * Children like when i am deleted does my children also get deleted Child Logic
 * must also be defined, then parent is deleted does child get deleted as well
 * 
 */

public class EntityChild {
	/*
	 * public static final int ONE_TO_ONE=0x2; public static final int
	 * MANY_TO_ONE=0x4; public static final int ONE_TO_MANY=0x8; public static
	 * final int MANY_TO_MANY=0x10;
	 */

	public static final int CHILD_DELETE = 0x2;
	private int entity_logic = 0;
	private FieldForeignKeyInterface foreign_key = null;
	private Entity entity, child = null;
	private boolean entity_was_new = false;

	public EntityChild(FieldForeignKeyInterface foreign_key, int entity_logic,
			Entity entity) {
		entity.addChild(this);
		this.entity = entity;
		this.entity_logic = entity_logic;
		this.foreign_key = foreign_key;
	}

	public FieldForeignKeyInterface getFieldForeignKey() {
		return foreign_key;
	}

	public Entity getEntity() {
		return entity;
	}

	public void delete() throws BindException {
		try {
			Entity child = foreign_key.getEntity();
			child.setConnection(entity.getConnection());
			for (child = child.find(foreign_key.getName() + " = '"
					+ entity.id.getAsString() + "'"); child != null; child = child
					.getNextEntity()) {
				if (shouldDeleteChild()) {
					child.delete();
				} else {
					child.getFields().get(foreign_key.getName())
							.setObject(null);
					child.save();
				}
			}
		} catch (Exception exception) {
			throw new BindException(exception);
		}
	}

	public void save() throws BindException {
		try {
			if (child != null) {
				child.getFieldByName(foreign_key.getName()).setObject(
						entity.id.getAsString());
				child.save();
			}
		} catch (Exception exception) {
			throw new BindException(exception);
		}
	}

	public void nullifyChild() {
		child = null;
	}

	public void rebind(Entity parent) {
		entity = parent;
		child = null;
	}

	/**
	 * Retruns the child If no child has been created, create_new - it will
	 * create a new one
	 */
	public Entity getChild(boolean create_new) throws BindException {
		try {
			// if (child == null) {
			// foreign_key.set(entity.id.getAsString());
			// child = foreign_key.retrieve(entity.getDBConnection());
			child = foreign_key.getNewLocal(entity.getConnection());
			child = child.find(foreign_key.getName() + " = '"
					+ entity.id.getAsString() + "' order by "
					+ child.id.getName() + " asc");
			if (child == null && create_new) {
				child = foreign_key.getNewLocal(entity.getConnection());
				((FieldForeignKeyInterface) child.getFields().map(foreign_key.getField()))
						.set(entity.id.getAsString());
			}
			// }
			return child;
		} catch (Exception exception) {
			throw new BindException(exception);
		}
	}

	public Entity get() throws BindException {
		return getChild(false);
	}

	/*
	 * public Entity get() throws BindException{ try { if (child == null) {
	 * foreign_key.set(entity.id.getAsString()); return
	 * foreign_key.retrieve(entity.getDBConnection()); } return child; } catch
	 * (Exception exception) { throw new BindException(exception); } }
	 */

	public boolean wasSqlWhereInvalid() {
		return entity_was_new;
	}

	/**
	 * Builds sql for child
	 */
	public String getSqlWhere() throws DataException {
		if (entity.id.getAsObject() == null) {
			entity_was_new = true;
		} else {
			entity_was_new = false;
		}
		return foreign_key.getName() + " = "
				+ Entity.asSQL(entity.id.getAsString());
	}

	public Entity getChildInstance() {
		return foreign_key.getEntity().getNewInstance();
	}

	/**
	 * Should the child be deleted with the parent
	 */
	public boolean shouldDeleteChild() {
		return ((entity_logic & 0x2) == CHILD_DELETE);
	}

	public static class VectorEntityChild implements java.io.Serializable {
		private Vector store = new Vector();

		public EntityChild get(int pos) {
			return (EntityChild) store.get(pos);
		}

		public void add(EntityChild item) {
			store.add(item);
		}

		public boolean remove(EntityChild item) {
			return store.remove(item);
		}

		public EntityChild remove(int pos) {
			return (EntityChild) store.remove(pos);
		}

		public int size() {
			return store.size();
		}

		/**
		 * Determines if the set contains the child class eclass
		 */
		public boolean contains(Class eclass) {
			for (int i = 0; i < size(); i++) {
				if (get(i).getFieldForeignKey().getEntity().getClass()
						.getName().equals(eclass.getName())) {
					return true;
				}
			}
			return false;
		}

		public void save() throws BindException {
			for (int i = 0; i < size(); i++) {
				get(i).save();
			}
		}

		public void delete() throws BindException {
			for (int i = 0; i < size(); i++) {
				get(i).delete();
			}
		}

		public EntityChild map(EntityChild p_child) {
			for (int i = 0; i < size(); i++) {
				if (get(i).getFieldForeignKey().getName().equals(
						p_child.getFieldForeignKey().getName())
						&& get(i).getFieldForeignKey().getEntity().getClass()
								.getName().equals(
										p_child.getFieldForeignKey()
												.getEntity().getClass()
												.getName())) {
					return get(i);
				}
			}
			return null;
		}
	}

}
